﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data.SqlClient;

namespace MetierDonnees
{
    public class AccesBD : IAccesBD
    {

        private const String hote = "U041\\SQLEXPRESS";
        private const String login = "dourthe";
        private const String pass = "";
        private const String bd = "banque";
        private SqlConnection connection;

        public AccesBD()
        {
            connection = new SqlConnection("Server=" + hote + ";Database=" + bd + ";User ID=" + login + ";Password=" + pass + ";Trusted_Connection=False");
        }

        ~AccesBD()
        {
            connection.Dispose();
        }
        
        //Methode pour recherche d'un utilisateur
        public Utilisateur extraireUtilisateur(String login, String motPasse)
        {
            int privilege = -1, idUtilisateur = -1;
            Object[][] values = sqlUntransactionalRequest("SELECT privilege,idUtilisateur, login, password, nom, prenom,adresse,telephone FROM utilisateur WHERE login = '" + login + "' AND password = '" + motPasse + "';");

            int.TryParse(values[0][0].ToString(), out privilege);
            int.TryParse(values[0][1].ToString(), out idUtilisateur);
            return new Utilisateur(privilege, values[0][2].ToString(), values[0][3].ToString(), values[0][4].ToString(), values[0][5].ToString(), values[0][6].ToString(), values[0][7].ToString(), idUtilisateur); 
        }

        public int sauverUtilisateur(Utilisateur utilisateur)
        {
            sqlExecute("UPDATE Utilisateur SET "
                + "login = '" + utilisateur.login + "', "
                + "password = '" + utilisateur.password + "', "
                + "nom = '" + utilisateur.nom + "', "
                + "prenom = '" + utilisateur.prenom + "', "
                + "adresse = '" + utilisateur.adresse + "', "
                + "telephone = '" + utilisateur.telephone + "' "
                + "WHERE idUtilisateur = " + utilisateur.idUtilisateur);
            
            return 1;
        }

        //Methode d'ajout dans les tables Conseiller, Client, Compte et Historique
        public int ajouterConseiller(Conseiller conseiller)
        {
            int idConseiller = sqlExecute("INSERT INTO Utilisateur(privilege,login,password,nom,prenom,adresse,telephone) VALUES('"
               + conseiller.privilege + "', '"
               + conseiller.login + "', '"
               + conseiller.password + "', '"
               + conseiller.nom + "', '"
               + conseiller.prenom + "', '"
               + conseiller.adresse + "', '"
               + conseiller.telephone + "')");
            return idConseiller;
        }

        public int ajouterClient(int idConseiller, Client nouveauClient)
        {
            int idClient = sqlExecute("INSERT INTO Utilisateur(privilege,login,password,nom,prenom,adresse,telephone) VALUES('" 
                + nouveauClient.privilege + "', '"
                + nouveauClient.login + "', '"
                + nouveauClient.password + "', '"
                + nouveauClient.nom + "', '"
                + nouveauClient.prenom + "', '"
                + nouveauClient.adresse + "', '"
                + nouveauClient.telephone + "')");

            sqlExecute("INSERT INTO GestionnaireClient(idGestionnaire,idClient) VALUES('"
                + idConseiller + "', '"
                + idClient + "')");
            return idClient;
        }
        
        public int ajouterCompte(int idClient, Compte nouveauCompte)
        { 
            int compte = sqlExecute("INSERT INTO Compte(solde, numero, idUtilisateur) VALUES("
                + nouveauCompte.solde + "', '"
                + nouveauCompte.numero + "', '"
                + idClient + "')");
            return compte;
        }

        public int ajouterHistorique(int idCompte, Historique historique)
        {
            int idHistorique = sqlExecute("INSERT INTO Operation(type, montant, date, libelle, numeroCompte) VALUES("
                + historique.type + "', '"
                + historique.montant + "', '"
                + historique.date + "', '"
                + historique.libelle + "', '"
                + idCompte + "')");
            return idHistorique;
        }
        //Methode pour extraire des tables Conseiller, Client, Compte et Historique
        public List<Conseiller> extraireConseillers()
        {
            List<Conseiller> result = new List<Conseiller>();
            Object[][] values = sqlUntransactionalRequest("SELECT privilege, login, password, nom, prenom, adresse, telephone, idUtilisateur FROM Utilisateur WHERE privilege = '" + Utilisateur.CONSEILLER +  "'");
            for (int i = 0; i < values.Length; i++)
            {
                result.Add(new Conseiller(int.Parse(((String)values[i][0])), (String)values[i][1], (String)values[i][2], (String)values[i][3], (String)values[i][4], (String)values[i][5], (String)values[i][6], int.Parse((String)values[i][7])));
            }
            return result;
        }

        public List<Client> extraireClients(int idConseiller)
        {
            List<Client> result = new List<Client>();
            Object[][] values = sqlUntransactionalRequest("SELECT u.privilege, u.login, u.password, u.nom, u.prenom, u.adresse, u.telephone, u.idUtilisateur FROM Utilisateur u, GestionnaireClient g WHERE privilege = '" + Utilisateur.CLIENT + "' AND u.idUtilisateur = g.idClient AND g.idGestionnaire = '" + idConseiller + "'");
            for (int i = 0; i < values.Length; i++)
            {
                result.Add(new Client(int.Parse(((String)values[i][0])), (String)values[i][1], (String)values[i][2], (String)values[i][3], (String)values[i][4], (String)values[i][5], (String)values[i][6], int.Parse((String)values[i][7])));
            }
            return result;
        }

        public List<Compte> extraireCompte(int idClient)
        {
            List<Compte> result = new List<Compte>();

            Object[][] values = sqlUntransactionalRequest("SELECT solde, numero, idUtilisateur FROM Compte WHERE idUtilisateur = '" + idClient + "'");
            for (int i = 0; i < values.Length; i++)
            {
                result.Add(new Compte(double.Parse((String)values[i][0]), (String)values[i][1], int.Parse((String)values[i][2])));
            }

            return result;
        }
        public List<Historique> extraireHistorique(int idCompte)
        {
            List<Historique> result = new List<Historique>();

            Object[][] values = sqlUntransactionalRequest("SELECT type, montant, date, libelle, idOperation, numeroCompte FROM Operation WHERE numeroCompte = '" + idCompte + "'");
            for (int i = 0; i < values.Length; i++)
            {
                result.Add(new Historique(int.Parse((String)values[i][0]), double.Parse((String)values[i][1]), DateTime.Parse((String)values[i][2]), (String)values[i][3], int.Parse((String)values[i][4]), (String)values[i][5]));
            }

            return result;
        }
        //Methode pour mettre à jour les tables de la BD
        public int sauverConseillers(List<Conseiller> conseillers)
        {
            foreach(Conseiller conseiller in conseillers){
                sqlExecute("UPDATE Utilisateur SET "
                    + "login = '" + conseiller.login + "', "
                    + "password = '" + conseiller.password + "', "
                    + "nom = '" + conseiller.nom + "', "
                    + "prenom = '" + conseiller.prenom + "', "
                    + "adresse = '" + conseiller.adresse + "', "
                    + "telephone = '" + conseiller.telephone + "' "
                    + "WHERE idUtilisateur = " + conseiller.idUtilisateur);
            }
            return 1;
        }

        public int sauverClients(List<Client> clients, int idConseiller)
        {
            foreach (Client client in clients)
            {
                sqlExecute("UPDATE Utilisateur SET "
                    + "login = '" + client.login + "', "
                    + "password = '" + client.password + "', "
                    + "nom = '" + client.nom + "', "
                    + "prenom = '" + client.prenom + "', "
                    + "adresse = '" + client.adresse + "', "
                    + "telephone = '" + client.telephone + "' "
                    + "WHERE idUtilisateur = " + client.idUtilisateur);
            }
            return 1;
        }

        public int sauverComptes(List<Compte> comptes, int idClient)
        {
            foreach (Compte compte in comptes)
            {
                sqlExecute("UPDATE Compte SET "
                    + "solde = '" + compte.solde + "', "
                    + "numero = '" + compte.numero + "', "
                    + "idUtilisateur = '" + compte.idUtilisateur + "' "
                    + "WHERE idUtilisateur = " + idClient );
            }
            return 1;
        }

        public int sauverHistorique(List<Historique> historiques, int idCompte)
        {
            foreach (Historique historique in historiques)
            {
                sqlExecute("UPDATE Utilisateur SET "
                    + "type = '" + historique.type + "', "
                    + "montant = '" + historique.montant + "', "
                    + "date = '" + historique.date + "', "
                    + "libelle = '" + historique.libelle + "', "
                    + "numeroCompte = '" + historique.numeroCompte + "', "
                    + "WHERE idOperation = " + historique.idOperation);
            }
            return 1;
        }

        //Methode pour supprimer des données de la BD
        public int supprimerClient(int idClient)
        {
            sqlExecute("DELETE FROM Utilisateur WHERE idUtilisateur = " + idClient);
            sqlExecute("DELETE FROM GestionnaireClient WHERE idClient = " + idClient);
            List<Compte> comptes = extraireCompte(idClient);
            for (int i = 0; i < comptes.Capacity; i++)
            {
                sqlExecute("DELETE FROM Operation WHERE numeroCompte = " + comptes[i].numero);
            }
            sqlExecute("DELETE FROM Compte WHERE idUtilisateur = " + idClient);
            return 1;    
        }

        public int supprimerConseiller(int idConseiller)
        {
            sqlExecute("DELETE FROM Utilisateur WHERE idUtilisateur = " + idConseiller);
            sqlExecute("DELETE FROM GestionnaireClient WHERE idGestionnaire = " + idConseiller);
            return 0;
        }
        public int supprimerCompte(int idCompte)
        {
            sqlExecute("DELETE FROM Compte WHERE numeroCompte = " + idCompte);
            sqlExecute("DELETE FROM Operation WHERE numeroCompte = " + idCompte);
            return 0;
        }
        public int supprimerHistorique(int idCompte)
        {
            sqlExecute("DELETE FROM Operation WHERE idUtilisateur = " + idCompte);
            return 0;
        }

        private int sqlExecute(string request)
        {
            int id = -1;

            connection.Open();
            SqlCommand com = connection.CreateCommand();
            com.Connection = connection;
            com.CommandText = request + " SELECT CAST(scope_identity() AS int)";
            try
            {
                com.ExecuteNonQuery();
                id = (Int32)com.ExecuteScalar();
            }
            catch(SqlException ex)
            {
                connection.Close();
                return -1;
            }
            connection.Close();
            return id;
        }

        private Object[][] sqlUntransactionalRequest(string request)
        {
            connection.Open();
            int i = 0;
            SqlCommand com = connection.CreateCommand();
            com.Connection = connection;
            com.CommandText = request;
            Object[][] result = new Object[com.ExecuteNonQuery()][];
            SqlDataReader reader = com.ExecuteReader();
            while (reader.Read())
            {
                reader.GetValues(result[i++]);
            }
            connection.Close();
            return result;
        }

    }
}
